<?php
// +---------------------------------------------------------------
// | EasyWeChat 公众号相关功能封装
// +---------------------------------------------------------------
// | Author: liang <23426945@qq.com>
// +---------------------------------------------------------------

declare(strict_types=1);

namespace app\common\lib\easywechat;

use EasyWeChat\Factory;
use app\common\logic\Config as LogicConfig;

class OfficialAccount
{
    public $app;

    /**
     * 初始化配置
     */
    public function __construct()
    {
        $official = LogicConfig::getBatchByType('official_account');
        $config = [
            'app_id'        => $official['official_appid'],
            'secret'        => $official['official_secret'],
            'response_type' => 'array', // 指定API调用返回结果的类型
        ];
        $this->app = Factory::officialAccount($config);
    }

    // +---------------------------------------------------------------
    // | 二维码
    // +---------------------------------------------------------------
    // | https://www.easywechat.com/4.x/basic-services/qrcode.html
    // +---------------------------------------------------------------

    /**
     * 生成临时二维码
     *
     * @param integer $uid 用户id
     */
    public function qrcode(int $uid)
    {
        // 创建临时二维码, 当公众号appid或开发者密钥配置错误时将抛出异常
        $result = $this->app->qrcode->temporary(strval($uid), 6 * 24 * 3600);
        if (isset($result['errcode']) && $result['errcode'] == 48001) {
            // 48001: 个人订阅号没有权限调用高级接口
            // api unauthorized rid: 615f013d-15fcf84b-054f4b9b
            fault($result['errmsg']);
        }
        // 获取二维码网址(返回二维码图片地址)
        return $this->app->qrcode->url($result['ticket']);
    }

    // +---------------------------------------------------------------
    // | 服务器配置
    // +---------------------------------------------------------------

    /**
     * 消息推服务器URL地址
     *
     * @param string $token 访问令牌Token
     */
    public function response(string $token)
    {
        // 消息推送接入验证
        $this->checkSignature($token);
        // 事件消息数据包
        $xml     = file_get_contents('php://input');                                 // 用户发送的消息数据包
        $object  = simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA);
        $message = json_decode(json_encode($object), true);
        // 根据用户发送不同类型的内容回复不同的消息
        switch ($message['MsgType']) {
            case 'event': // 文本消息
                $content = call_user_func([\app\api\logic\Official::class, 'event'], $message);
                break;
            default:
                $content = '暂未设置自动回复'; // 解决提示 "该公众号提供的服务出现故障，请稍后再试"
                break;
        }
        // 回复文本消息
        $this->app->server->push(function ($message) use ($content) {
            return $content;
        });
        $this->app->server->serve()->send();
    }

    /**
     * 开发者服务器接入验证
     *
     * @param string $token Token(令牌)
     */
    private function checkSignature(string $token)
    {
        $nonce     = $_GET["nonce"] ?? '';
        $signature = $_GET["signature"] ?? '';
        $timestamp = $_GET["timestamp"] ?? '';
        $tmpArr = array($token, $timestamp, $nonce);
        sort($tmpArr, SORT_STRING);
        $tmpStr = implode('', $tmpArr);
        $tmpStr = trim(sha1($tmpStr));
        if (empty($token)) die('未设置消息推送token令牌');
        if (empty($signature) || empty($tmpStr) || empty($nonce)) die('非法请求！！！');
        if ($tmpStr != $signature) die('签名验证错误');
        isset($_GET['echostr']) ? die($_GET['echostr']) : '';
    }

    // +---------------------------------------------------------------
    // | 网页授权
    // +---------------------------------------------------------------
    // | https://www.easywechat.com/4.x/official-account/oauth.html
    // +---------------------------------------------------------------

    /**
     * 调起网页授权
     */
    public function auth()
    {
        // 当前页面地址
        $url = urlencode(request()->url(true));
        // 回调地址
        $redirect_uri = u('official/userinfo', ['target_url' => $url]);
        // 调起网页授权页
        $this->app->oauth->scopes(['snsapi_userinfo'])->redirect($redirect_uri)->send();
    }

    /**
     * 获取用户信息
     */
    public function getUserInfo()
    {
        // 获取 OAuth 授权结果用户信息
        $user = $this->app->oauth->user();
        // 原始API返回的结果
        $data = $user->getOriginal();
        halt($user, $data);
    }

    // +---------------------------------------------------------------
    // | 模板消息
    // +---------------------------------------------------------------
    // | https://www.easywechat.com/4.x/official-account/template_message
    // +---------------------------------------------------------------

    /**
     * 发送模板消息
     *
     * @param string $openid      接收者用户openid
     * @param string $template_id 模板消息模板id
     * @param array  $data        模板消息数据
     * @param array  $target      跳转地址
     */
    public function templateMessage(string $openid, string $template_id, array $data, $target = [])
    {
        $params = [
            'data'        => $data,
            'touser'      => $openid,
            'template_id' => $template_id,
        ];
        $params = array_merge($target, $params);
        // 发送模板消息
        return $this->app->template_message->send($params);
    }
}
